/* Constants */
FADE_DIRECTION_IN		= 1
FADE_DIRECTION_OUT	= 2

/* Constructor */
Fader = class( function( self, ... )

	/* Read the parameters as key / value */
	local keyframes			= {}
	local key				= 0
	local i					= 1
	while key != nil do
		
		/* Read keyframe */
		key					= select( i, ... )
		
		/* If valid, set it not to break the animation and store it */
		if IsValidInstance( key, Keyframe ) then
			key:SetContinuous()
			table.insert( keyframes, key )
		
		/* Otherwise, stop */
		else
			break
		end
		
		/* Increment loop variable */
		i					= i + 1
	end
	local fadeInTimeParam	= select( i, ... )
	local fadeOutTimeParam	= select( i + 1, ... )

	/* Create an animation */
	self.Animation			= Animation( keyframes, 1, 0 )
	
	/* Default values */
	self.Direction			= FADE_DIRECTION_IN
	self.InDuration			= fadeInTimeParam or 1
	self.OutDuration		= fadeOutTimeParam or 0.5
	self.LinkedObject		= nil
	self.Animation.LinkedObject = self
	
	/* Hooks */
	self.OnFadeEnded		= nil
	self.OnFading			= nil
	self.OnFadeComplete		= nil
	self.Animation.OnEnded	= self.FadeEnded
	self.Animation.OnTick	= self.Fading
	self.Animation.OnFirstKeyReached	= self.FadeComplete
	self.Animation.OnLastKeyReached		= self.FadeComplete
end )

/* Set the fade in duration */
Fader.SetInDuration = function( self, value )

	/* Ensure valid number */
	if not IsNumber( value ) or value <= 0 then
		DEBUG:ErrMsg( "Duration must be a number greater than 0.", "Fader.SetInDuration" )
	end
	
	/* Set duration */
	self.InDuration			= value
end

/* Set the fade out duration */
Fader.SetOutDuration = function( self, value )

	/* Ensure valid number */
	if not IsNumber( value ) or value <= 0 then
		DEBUG:ErrMsg( "Duration must be a number greater than 0.", "Fader.SetOutDuration" )
	end
	
	/* Set duration */
	self.OutDuration		= value
end

/* Check if the fader is at min */
Fader.IsMinValue = function( self )
	return self.Animation:GetCurrentPosition() <= 0
end

/* Check if the fader is at max */
Fader.IsMaxValue = function( self )
	return self.Animation:GetCurrentPosition() >= 1
end

/* Get the current value */
Fader.GetCurrentValue = function( self )
	return self.Animation:GetCurrentValue()
end

/* Get the current position */
Fader.GetCurrentPosition = function( self )
	return self.Animation:GetCurrentPositionRelative()
end

/* Fade in / out */
Fader.Fade = function( self )

	/* Debug output */
	 if zed then zed = zed end -- DEBUG:Msg( "Fading started", "Fader.Fade" )

	/* If the animation is running, pause it */
	if self.Animation:IsRunning() and not self.Animation:IsPaused() then
		self.Animation:Pause()
	end
	
	/* Update the duration */
	if self.Direction == FADE_DIRECTION_IN then
		self.Animation:SetDuration( self.InDuration )
	else
		self.Animation:SetDuration( self.OutDuration )
	end
	
	/* If the animation has been paused, resume it */
	if self.Animation:IsPaused() then
		self.Animation:Resume()
		
	/* Otherwise, start it */
	else
		self.Animation:Play()
	end
end

Fader.Reverse = function( self )
	if self.Direction == FADE_DIRECTION_OUT then
		self.Direction		= FADE_DIRECTION_IN
		self.Animation.Reversed = false
	else
		self.Direction		= FADE_DIRECTION_OUT
		self.Animation.Reversed = true
	end
end

/* Fade in */
Fader.FadeIn = function( self )

	/* Toggle direction */
	if self.Direction == FADE_DIRECTION_OUT then
		self.Direction		= FADE_DIRECTION_IN
		self.Animation.Reversed = false
	end
	
	/* Fade */
	self:Fade()
end

/* Fade out */
Fader.FadeOut = function( self )

	/* Toggle direction */
	if self.Direction == FADE_DIRECTION_IN then
		self.Direction		= FADE_DIRECTION_OUT
		self.Animation.Reversed = true
	end
	
	/* Fade */
	self:Fade()
end

/* Release resources */
Fader.Dispose = function( self )
	self.Animation:Stop()
end

/* Called when the animation has ended */
Fader.FadeEnded = function( animation )

	/* Retrieve the fader */
	local self = animation.LinkedObject
	
	/* Raise the event if hooked */
	if self.OnFadeEnded then
		self.OnFadeEnded( self )
	end
end

/* Called while the animation is running */
Fader.Fading = function( animation )
	
	/* Retrieve the fader */
	local self = animation.LinkedObject
	
	/* Raise the event if hooked */
	if self.OnFading then
		self.OnFading( self )
	end
end

/* Called when first or last keyframe has been reached */
Fader.FadeComplete = function( animation )
	
	/* Retrieve the fader */
	local self = animation.LinkedObject
	
	/* Raise the event if hooked */
	if self.OnFadeComplete then
		self.OnFadeComplete( self )
	end
end